module mculib.arm.scb;
/**
* 系统控制块
*/

import mculib.chip;

version(None):

import arm.misc;


private enum bool hasBusPeriph = HasPeriph!("SCB");
static if(hasBusPeriph):

//import core.volatile;
import arm.volatile;

import arm.builtins;
import arm.bus;
import arm.cortex_m;
//import arm;
//import arm.scs;

struct CPUID_Type
{
    @disable this();
    align(1):
    uint Revision:4;        ///< 修订
    uint PartNo:12;         ///< 部件号
    uint Constant:4;        ///< 常量
    uint Variant:4;         ///< 变体
    uint Implementer:8;     ///< 实现者
    static assert(this.sizeof == uint.sizeof, "CPUID_Type size error");
}

enum PriGroup_Type
{
    Group_0 = 0x07,    ///< 0bit宽度 抢占优先级，4bit宽度 响应优先级
    Group_1 = 0x06,    ///< 1bit宽度 位抢占优先级，3bit宽度 位响应优先级
    Group_2 = 0x05,    ///< 2bit宽度 位抢占优先级，2bit宽度 位响应优先级
    Group_3 = 0x04,    ///< 3bit宽度 位抢占优先级，1bit宽度 位响应优先级
    Group_4 = 0x03,    ///< 4bit宽度 位抢占优先级，0bit宽度 位响应优先级
}

/// 重置参数
enum ResetFlag
{
    None = 0,
    // 重置中断
    Reset_Interrupt = 0b0110,
    // 重置向量
    Reset_Vect = 0b0101,
    Reset_All = Reset_Interrupt | Reset_Vect,
}

//final abstract class
static interface SCB //: MMIOBus!(Peripherals.SCB)
{
    public{
        import core.bitop:bsf;
        
        enum SCB_Type* mBase = Peripherals.SCB;
        //enum VECTKEY = 0x05FA;
        //enum VECTKEY_Pos = mBase.mask_AIRCR.VECTKEY.bsf();
        //enum VECTKEY = 0x05FA << mBase.mask_AIRCR.VECTKEY.bsf();

        pragma(crt_constructor,CrtPriority!(FlagCrt.ROOT,5))
        static this()
        {
            /// 设置默认优先级分组
            PriorityGroup(PriGroup_Type.Group_4);
        }
    }
    /// 模板操作
    package{
        /*
        @property static void MMIO_AIRCR(string fn,T = uint)(T v) if(__traits(hasMember, mBase, "AIRCR"))
            => MMIO_Bitfield!("AIRCR",fn,T)(v);
        */
        /*
        @property static auto MMIO_AIRCR(string fn,T = uint)() if(__traits(hasMember, mBase, "AIRCR"))
            => MMIO_Bitfield!("AIRCR",fn)();
            */
        /// 核心中断使能
        /// 核心中断禁止

    }
    /// CPUID 基本信息寄存器
    static immutable(CPUID_Type) CPUID() @property
    {
        return cast(immutable(CPUID_Type))mBase.CPUID;
    }
    /// 获取优先级分组
    static PriGroup_Type PriorityGroup() @property 
    {
        return cast(PriGroup_Type)mBase.AIRCR.PRIGROUP();
    }
    /// 设置优先级分组
    static void PriorityGroup(PriGroup_Type priGroup) @property
    {
        auto regval = mBase.AIRCR;
        //mBase.mask_AIRCR.VECTKEY
        //mBase.mask_AIRCR.PRIGROUP
        enum VECTKEY_val = 0x05FA;

        regval.VECTKEY = VECTKEY_val;
        regval.PRIGROUP = priGroup;
        mBase.AIRCR = regval;

        /*
        scope(exit) __dsb();
        __dsb();
        */
        //enum mask = RegMask!("AIRCR");
        //enum pos = mBase.mask_AIRCR.PRIGROUP.bsf();
        //uint old = MMIO_Bitfield_Get!("AIRCR",mask,uint)();

        //uint old = MMIO_RegGet!(&mBase.AIRCR)();
        //old &= ~(mBase.mask_AIRCR.PRIGROUP|mBase.mask_AIRCR.VECTKEY);
        //uint nval = (priGroup << pos) | (VECTKEY);
        //MMIO_RegSet(&mBase.AIRCR,nval);
        //mBase.AIRCR = nval;

        //MMIO_AIRCR!("PRIGROUP",uint)(priGroup);
        
    }

    /**
    * 设置系统中断优先级
    * Params: 
    * mIrq = 中断号
    * mPriority = 优先级
    */
    @property static void Priority(IRQn_Core mIrq)(uint mPriority) if(mIrq < 0)
    {
        enum idx = mIrq & 0x0F;
        enum pos = idx >> 2;
        __traits(getMember,mBase,"SHPR"~pos.stringof).opDispatch!("PRI_"~idx.stringof) = mPriority;
    }
    @property static void Priority(IRQn_Core mIrq,uint mPriority) 
    in(mIrq < 0)
    {
        enum addr = cast(size_t)(mBase) + (mBase.SHPR1.offsetof);
        auto idx = (cast(uint)mIrq & 0x0f) - 0x04;
        auto paddr = cast(ubyte*)(addr + idx);
        ubyte nval = cast(ubyte)(mPriority << (8 - PriorityWidth));

        auto reg = cast(RW_Reg!(null,ubyte)*)paddr;
        *reg = nval;
        //MMIO_RegSet(paddr,nval);

    }
    
    @property static uint Priority(IRQn_Core mIrq)() if(mIrq < 0)
    {
        //mBase.SHPR1
        enum idx = mIrq & 0x0F;
        enum pos = idx >> 2;
        return __traits(getMember,mBase,"SHPR"~pos.stringof).opDispatch!("PRI_"~idx.stringof)();
        
    }
    
    /**
    * 获取中断对应的优先权
    * Params: mIrq = 中断号
    */
    @property static uint PriorityGet(IRQn_Core mIrq)   // 函数实现
    in(mIrq < 0 ,"mIrq must be a negative number")
    {
        enum addr = cast(size_t)(mBase) + (mBase.SHPR1.offsetof);
        auto idx = (cast(uint)mIrq & 0x0f) - 0x04;
        auto paddr = cast(ubyte*)(addr + idx);
        auto reg = cast(RW_Reg!(null,ubyte)*)paddr;
        auto v = *reg;
        //auto v = MMIO_RegGet(paddr);
        return (v >> (8 - PriorityWidth));
    }
    /**
    * 设置中断对应的优先权
    * Params: mIrq = 中断号
    * mPriority = 优先级
    */
    @property static void PrioritySet(IRQn_Core mIrq,uint mPriority)   // 函数实现
    in(mIrq < 0 ,"mIrq must be a negative number")
    {
        enum addr = cast(size_t)(mBase) + (mBase.SHPR1.offsetof);
        auto idx = (cast(uint)mIrq & 0x0f) - 0x04;
        auto paddr = cast(ubyte*)(addr + idx);
        ubyte nval = cast(ubyte)(mPriority << (8 - PriorityWidth));

        auto reg = cast(volatileUByte*)paddr;
        *reg = nval;

    }
    
    /**
    * 系统重新启动
    * Params: rflags = 重置标志 
    */
    static void SystemReset(ResetFlag rflags = ResetFlag.Reset_All)
    //in((rflags & ~Maker_Flags.AIRCR_RESET_MASK) == 0)
    {
        enum VECTKEY_val = 0x05FA;
        auto regval = mBase.AIRCR;
        regval = 0x00;
        regval.VECTKEY = VECTKEY_val;
        regval.SYSRESETREQ = rflags;
        //regval.PRIGROUP = 0x07;
        __dsb();
        mBase.AIRCR = regval;
        __dsb();
        while(1) __nop();
    }


}

/+
version(NONE):



/// 优先级分组标志


package{
    /// CPUID 基本信息寄存器位结构
    struct sCPUID{
        align(1):
        uint Revision:4;        ///< 修订
        uint PartNo:12;         ///< 部件号
        uint Constant:4;        ///< 常量
        uint Variant:4;         ///< 变体
        uint Implementer:8;     ///< 实现者
        ref T opCast(T:uint)() const
        {
            return *cast(T*)&this;
        }
    }
    debug static assert(sCPUID.sizeof == uint.sizeof);

    /// 中断控制和状态寄存器位结构
    struct sICSR{
        align(1):
        uint VECTACTIVE:9;      ///< 当前活动的中断号
        uint Reserved1:2;       ///< 保留
        uint RETTOBASE:1;       ///< 返回基线
        uint VECTPENDING:7;     ///< 当前挂起的中断号
        uint Reserved2:3;
        uint IsrPending:1;      ///< 中断挂起标志
        uint Reserved3:2;
        uint PENDSTCLR:1;       ///< 清除挂起的 SysTick 中断
        uint PENDSTSET:1;       ///< 设置挂起的 SysTick 中断
        uint PENDSVCLR:1;       ///< 清除挂起的 PendSV 中断
        uint PENDSVSET:1;       ///< 设置挂起的 PendSV 中断
        uint Reserved4:2;
        uint NMIPENDSET:1;      ///< 设置挂起的 NMI 中断
        ref T opCast(T:uint)() const
        {
            return *cast(T*)&this;
        }
    }
    debug static assert(sICSR.sizeof == uint.sizeof);

    /// 系统控制寄存器位结构
    struct sAIRCR{
        align(1):
        uint VECTRESET:1;       ///< 重置向量表
        uint VECTCLRACTIVE:1;   ///< 清除活动的中断
        uint SYSRESETREQ:1;     ///< 系统复位请求
        uint :5;
        uint PRIGROUP:3;        ///< 优先级分组
        uint :4;
        uint ENDIANESS:1;       ///< 大小端
        uint VECTKEYSTAT:16;    ///< 寄存器保护

        ref T opCast(T:uint)() const
        {
            return *cast(T*)&this;
        }
    }
    debug static assert(sAIRCR.sizeof == uint.sizeof);
}




/**
    系统控制
    * 0xe000ed00 ~ 0xe000ed3f
*/
final abstract class SCB{
    /// 外设地址
    enum PeripheralAddress = CorePeripheralAddress.SCB_Base;
    /// SCB 结构体
    struct SCB_Struct
    {
        uint CPUID;         ///< CPUID 基本信息寄存器 , offset: 0x00
        uint ICSR;          ///< 中断控制和状态寄存器 , offset: 0x04
        uint VTOR;          ///< 中断向量表偏移寄存器 , offset: 0x08
        uint AIRCR;         ///< 系统控制寄存器 , offset: 0x0C
        uint SCR;           ///< 系统控制寄存器 , offset: 0x10
        uint CCR;           ///< 配置和控制寄存器 , offset: 0x14
        ubyte[12] SHP;      ///< 系统控制寄存器 , offset: 0x18
        uint SHCSR;         ///< 系统控制寄存器 , offset: 0x24
        uint CFSR;          ///< 配置和控制寄存器 , offset: 0x28
        uint HFSR;          ///< 配置和控制寄存器 , offset: 0x2C
        uint DFSR;          ///< 配置和控制寄存器 , offset: 0x30
        uint MMFAR;         ///< 配置和控制寄存器 , offset: 0x34
        uint BFAR;          ///< 配置和控制寄存器 , offset: 0x38
        uint AFSR;          ///< 配置和控制寄存器 , offset: 0x3C
        uint[2] PFR;        ///< 配置和控制寄存器 , offset: 0x40
        uint DFR;           ///< 配置和控制寄存器 , offset: 0x48
        uint ADR;           ///< 配置和控制寄存器 , offset: 0x4C
        uint[4] MMFR;       ///< 配置和控制寄存器 , offset: 0x50
        uint[5] ISAR;       ///< 配置和控制寄存器 , offset: 0x60
        uint[5] RESERVED0;  ///< 保留 , offset: 0x74
        uint CPACR;         ///< 协处理器访问控制寄存器 , offset: 0x88
    }

    /// 掩码标志
    enum Maker_Flags : uint
    {
        CPUID_IMPLEMENTER = combineMasks!(24,25,26,27,28,29,30,31),///< CPUID 寄存器的实现者标志
        CPUID_VARIANT = combineMasks!(20,21,22,23),               ///< CPUID 寄存器的变体标志
        CPUID_ARCHITECTURE = combineMasks!(16,17,18,19),          ///< CPUID 寄存器的架构标志
        CPUID_PARTNO = combineMasks!(4,5,6,7,8,9,10,11,12,13,14,15),///< CPUID 寄存器的部件号标志
        CPUID_REVISION = combineMasks!(0,1,2,3),                  ///< CPUID 寄存器的修订标志



        AIRCR_VECTKEY_POS = 16,                         ///< AIRCR 寄存器的 VECTKEY 位偏移
        AIRCR_VECTKEY = 0x05FA << AIRCR_VECTKEY_POS,    ///< AIRCR 寄存器的 VECTKEY 位偏移
        AIRCR_VECTKEY_MASK = 0xFFFF << AIRCR_VECTKEY_POS,///< AIRCR 寄存器的 VECTKEY 位偏移
        AIRCR_ENDIANESS = combineMasks!(15),             ///< 大小端模式
        AIRCR_PRIGROUP = combineMasks!(8,9,10),          ///< 抢占优先级 掩码
        AIRCR_SYSRESETREQ = combineMasks!(2),            ///< 系统复位请求
        AIRCR_VECTCLRACTIVE = combineMasks!(1),          ///< 清除活动中断
        AIRCR_VECTRESET = combineMasks!(0),              ///< 复位中断向量表
        AIRCR_RESET_MASK = AIRCR_SYSRESETREQ | AIRCR_VECTCLRACTIVE | AIRCR_VECTRESET,///< AIRCR 寄存器的复位位掩码
        AIRCR_Filter = AIRCR_VECTKEY_MASK | AIRCR_ENDIANESS | AIRCR_PRIGROUP | AIRCR_SYSRESETREQ | AIRCR_VECTCLRACTIVE | AIRCR_VECTRESET,///< AIRCR 寄存器的过滤器

        SHCSR_USGFAULTENA = combineMasks!(18),           ///< 使用故障使能
        SHCSR_BUSFAULTENA = combineMasks!(17),           ///< 总线故障使能
        SHCSR_MEMFAULTENA = combineMasks!(16),           ///< 内存故障使能
        SHCSR_SVCALLPENDED = combineMasks!(15),          ///< SVC 挂起
        SHCSR_BUSFAULTPENDED = combineMasks!(14),        ///< 总线故障挂起
        SHCSR_MEMFAULTPENDED = combineMasks!(13),        ///< 内存故障挂起
        SHCSR_USGFAULTPENDED = combineMasks!(12),        ///< 使用故障挂起
        SHCSR_SYSTICKACT = combineMasks!(11),            ///< SysTick 活动
        SHCSR_PENDSVACT = combineMasks!(10),             ///< PendSV 活动
        SHCSR_MONITORACT = combineMasks!(8),             ///< 监视器活动
        SHCSR_SVCALLACT = combineMasks!(7),              ///< SVC 活动
        SHCSR_USGFAULTACT = combineMasks!(3),            ///< 使用故障活动
        SHCSR_BUSFAULTACT = combineMasks!(1),            ///< 总线故障活动
        SHCSR_MEMFAULTACT = combineMasks!(0),            ///< 内存故障活动


    }

    /// 寄存器指针
    enum shared(SCB_Struct*) pSCB = RegMap!(PeripheralAddress, SCB_Struct);
    // 私有读取寄存器结构体
    private { 
        /// CPUID 寄存器
        @property
        pragma(inline,true)
        static sCPUID Reg_CPUID()
        {
            return cast(sCPUID)(ReadMemory!(&pSCB.CPUID,uint)());
        }
        @property
        pragma(inline,true)
        static void Reg_CPUID(sCPUID value)
        {
            WriteMemory!(&pSCB.CPUID)(cast(uint)value);
        }

        /// AIRCR 寄存器
        @property
        pragma(inline,true)
        static sAIRCR Reg_AIRCR()
        {
            return cast(sAIRCR)(ReadMemory!(&pSCB.AIRCR,uint)());
        }
        @property
        pragma(inline,true)
        static void Reg_AIRCR(sAIRCR value)
        {
            //WriteMemory!(&pSCB.AIRCR)(*cast(uint*)&value);
            WriteMemory!(&pSCB.AIRCR)(cast(uint)value);
        }
        
    }

    /**
    * 系统重新启动
    * Params: rflags = 重置标志 
    */
    static void SystemReset(ResetFlag rflags = ResetFlag.Reset_All)
    in((rflags & ~Maker_Flags.AIRCR_RESET_MASK) == 0)
    {
        __dsb();
        uint oPri = ReadMemory!(&pSCB.AIRCR,uint)();
        oPri &= Maker_Flags.AIRCR_PRIGROUP;
        WriteMemory!(&pSCB.AIRCR)(
            Maker_Flags.AIRCR_VECTKEY | 
            oPri |
            rflags 
            );
        __dsb();
        while(1) __nop();
    }


    /**
    * 优先级分组
    */
    @property
    static void PriorityGroup(PriGroup pgroup)
    in((pgroup & ~Maker_Flags.AIRCR_PRIGROUP) == 0)
    {
        sAIRCR oAIRCR = Reg_AIRCR();                            /// 读取原始值
        oAIRCR.PRIGROUP = pgroup;                               /// 设置优先级分组
        Reg_AIRCR(oAIRCR);                                      /// 写入寄存器
    }
    @property
    static PriGroup PriorityGroup()
    {
        return cast(PriGroup)(Reg_AIRCR().PRIGROUP);
    }

    /**
    * 设置中断优先级
    */
    static void SetInterruptPriority(IRQn_Ext mIRQn, uint priority)
    in(mIRQn >= 0)
    {
        //NVIC.SetPriorityGrouping(mIRQn, priority);
    }

    /**
    * 设置中断优先级 $(D IRQn_Core)
    */
    @property
    static void Priority(IRQn_Core mIRQn, uint priority)
    in(mIRQn < 0)
    {
        uint selidx = ((cast(int)mIRQn) & 0x0Fu) - 4u;
        ubyte val = cast(ubyte)(priority << (8 - PriorityWidth));
        //SCB.SH
        //pSCB.SHP[selidx] = cast(ubyte)(priority << (8 - PriorityWidth));
        volatileStore(cast(ubyte*)(&pSCB.SHP + selidx),val);

    }
    /**
    * 获取中断优先级 $(D IRQn_Core)
    * Params: 
    * mIRQn = 中断号
    * PreemptPriority = 抢占优先级
    * SubPriority = 子优先级
    */
    static void SetPriority(IRQn_Core mIRQn, uint PreemptPriority,uint SubPriority)
    {
        
        //uint priority = (PreemptPriority << (8 - PriorityWidth)) | (SubPriority & ((1u << (8 - PriorityWidth)) - 1u));
        uint priority = NVIC_EncodePriority(PriorityGroup(),PreemptPriority,SubPriority);
        Priority(mIRQn, priority);
    }



}
+/